package com.jmx.mstcodesandbox.javasandbox;


import cn.hutool.core.util.ArrayUtil;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.model.*;
import com.jmx.mstcodesandbox.CodeSandBox;
import com.jmx.mstcodesandbox.model.ProcessInfo;
import com.jmx.mstcodesandbox.utils.DockerExecUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
@Component("docker")
public class JavaDockerCodeSandBox extends JavaAbstractCodeSandBoxTemplate implements CodeSandBox {
    @Resource
    private DockerClient dockerClient;

    @Override
    public ProcessInfo execute(String inputArgs, String userCodeDir) {
        // 通过有jdk环境的镜像创建可交互的docker容器，在容器创建时就将编译好的文件放入容器中
        String imageName = "openjdk:8-alpine";
        CreateContainerCmd containerCmd = dockerClient.createContainerCmd(imageName);
        HostConfig hostConfig = new HostConfig();
        //编译后的代码服务器路径和docker容器的路径映射
        hostConfig.setBinds(new Bind(userCodeDir, new Volume("/app")));
        //设置容器执行最大内存
        hostConfig.withMemory(100 * 1000 * 1000L);
        CreateContainerResponse createContainerResponse = containerCmd
                .withHostConfig(hostConfig)
                .withAttachStderr(true)
                .withAttachStdin(true)
                .withAttachStdout(true)
                .withTty(true)
                .withNetworkDisabled(true)//禁用网路功能，防止用户使用网络
                .exec();
        String containerId = createContainerResponse.getId();
        // 启动容器

        dockerClient.startContainerCmd(containerId).exec();
        String[] inputArgsArray = inputArgs.split(" ");
        String[] cmdArray = ArrayUtil.append(new String[]{"java", "-cp", "/app", USER_CODE_CLASS_NAME}, inputArgsArray);
        return DockerExecUtil.executeCmd(dockerClient, containerId, cmdArray);
    }
}
